<!DOCTYPE html>
<html>

<head>
    <title></title>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="../lib/leaflet/leaflet.css">
    <link rel="stylesheet" type="text/css" href="../lib/leaflet-geoman/leaflet-geoman.css">
    <link rel="stylesheet" type="text/css" href="../lib/markerCluster/markerCluster.css">
    <link rel="stylesheet" type="text/css" href="../lib/markerCluster/markerCluster.Default.css">
    <style type="text/css">
        html {
            height: 100%;
            padding: 0;
            margin: 0;
        }

        body,
        #map {
            height: 98%;
        }
    </style>
    <script type="text/javascript" src="../lib/leaflet/leaflet.js"></script>
    <script type="text/javascript" src='../src/mi_leaflet.ChineseTmsProviders.js'></script>
    <script type="text/javascript" src='../lib/leaflet-geoman/leaflet-geoman.min.js'></script>
    <script type="text/javascript" src='../lib/leaflet-pip/leaflet-pip.js'></script>
    <script type="text/javascript" src='../lib/markerCluster/markercluster.js'></script>
    <script type="text/javascript" src='../lib/heat/leaflet-heat.js'></script>
</head>
<body>
<div>
    <button onclick="showHeatMap()">热力图</button>
    <button onclick="showAllLayers()">非热力图</button>
</div>
<div id='map'></div>
</body>
<script type="text/javascript">
    var normalm = L.tileLayer.chinaProvider('GaoDe.Normal.Map', {
        maxZoom: 18,
        minZoom: 3
    });
    var normal = L.layerGroup([normalm]);
    var map = L.map("map", {
        center: [36.70820977, 119.10748243],
        zoom: 18,
        layers: [normal],
        zoomControl: true,
        trackResize: true
    });
    //初始化绘制插件
    L.PM.initialize();
    //添加左侧绘制控件
    map.pm.addControls({
        position: 'topleft',
        drawCircle: false,
        drawPolyline: false,
        drawCircleMarker: false,
        cutPolygon: false,
        editMode: false,
        dragMode: false
    });
    //中文
    map.pm.setLang('zh');

    //全部经纬度
    let latlngs = [];
    // 热力图的纬度，经度，强度
    let heatLatlngs = [];
    //热力图layer
    let heatLayer = '';
    //标记组
    let markers = '';
    //点与多边形从属关系
    let pointBelongs = [];

    //绘制开始事件
    map.on('pm:drawstart', e => {
        if (e.shape === 'Marker') {
            document.getElementById("map").style.cursor = "none";
        } else {
            document.getElementById("map").style.cursor = "grab";
        }
    });

    //绘制模式关闭
    map.on('pm:drawend', e => {
        document.getElementById("map").style.cursor = "grab";
    });

    //绘制完成事件
    map.on('pm:create', e => {
        let shape = e.shape;
        //标记
        if ('Marker' === shape) {
            markerInit(e.layer);
            latlngs.push({'Marker': e.layer._latlng});
            //添加热力图
            heatLatlngs.push([e.layer._latlng.lat, e.layer._latlng.lng]);
        }
        //矩形
        if ('Rectangle' === shape) {
            polygonInit(e.layer);
            latlngs.push({'Rectangle': e.layer._latlngs[0]});
        }
        //多边形
        if ('Polygon' === shape) {
            polygonInit(e.layer);
            latlngs.push({'Polygon': e.layer._latlngs[0]});
        }
    });

    //移除事件
    map.on('pm:remove', e => {
        latlngs = [];
        heatLatlngs = [];
        let layers = map.pm.getGeomanLayers();
        if (layers) {
            for (let i = 0; i < layers.length; i++) {
                //标记
                if (layers[i].pm._shape === 'Marker') {
                    latlngs.push({'Marker': layers[i]._latlng});
                    heatLatlngs.push([layers[i]._latlng.lat, layers[i]._latlng.lng]);
                }
                //矩形
                if (layers[i].pm._shape === 'Rectangle') {
                    latlngs.push({'Rectangle': layers[i]._latlngs[0]});
                }
                //多边形
                if (layers[i].pm._shape === 'Polygon') {
                    latlngs.push({'Polygon': layers[i]._latlngs[0]});
                }
            }
        }
    });

    markerGroup();

    //点转为数量
    function markerGroup() {
        markers = L.markerClusterGroup({
            //将鼠标悬停在群集上时，它将显示其标记的范围
            showCoverageOnHover: true,
            //单击群集时，我们会缩放到其边界。
            zoomToBoundsOnClick: true,
            //当您单击底部缩放级别的群集时，我们将对其进行蜘蛛操作，以便您可以查看其所有标记。
            spiderfyOnMaxZoom: false,
            //在此缩放级别及更低的级别，标记将不会聚类。
            disableClusteringAtZoom: 16,
            //群集将从中心标记覆盖的最大半径（以像素为单位）。默认值80。减少将创建更多更小的群集。
            // 您还可以使用接受当前地图缩放并返回最大簇半径（以像素为单位）的函数。
            maxClusterRadius: 80,
            //布尔值，用于将addLayer的处理分成较小的间隔，以使页面不会冻结。
            chunkedLoading: true,
            //addLayers在暂停让其余页面处理之前工作的时间间隔（以毫秒为单位）。特别是，这可以防止在添加大量标记时冻结页面。默认为200ms。
            chunkInterval:50
        });
        map.addLayer(markers);
    }

    //标记需要执行的操作
    function markerInit(markerLayer) {
        //点转为数量
        markers.addLayer(markerLayer);
        //点击事件
        markerLayer.on('click', e => {
            console.log(e.latlng);
        });
        //弹出框
        markerLayer.bindPopup('我是标记');
    }

    //多边形需要执行的操作
    function polygonInit(polygonLayer) {
        //点击事件
        polygonLayer.on('click', e => {
            //点击点的坐标
            console.log(e.latlng);
            //多边形的坐标数组
            console.log(polygonLayer._latlngs);
        });
    }

    //地图缩放事件
    map.on('zoomend', e => {
        //动态设置热点图最大强度的缩放级别
        if (heatLayer) {
            heatLayer.options.maxZoom = getHeatMaxZoom();
        }
    });

    //动态设置热力图最大强度缩放级别
    function getHeatMaxZoom() {
        return map.getZoom() + 2;
    }

    //热力图
    function showHeatMap() {
        removeAll();//移除所有layer
        if (!heatLatlngs) {
            return;
        }
        heatLayer = L.heatLayer(heatLatlngs, {
            radius: 25,//每一个热图的“点”的半径，25默认
            maxZoom: getHeatMaxZoom(),//点达到最大强度的缩放级别（强度随缩放缩放），maxZoom默认情况下等于地图
            max: 1.0,//最大点强度，1.0默认情况下
            blur: 15,//15默认情况下，模糊量
            gradient: {
                0.5: 'blue',
                0.65: '#75D3F8',
                0.7: '#00FF00',
                0.9: '#ffea00',
                1.0: 'red'
            }//颜色渐变配置
        }).addTo(map);
    }

    //展示全部图层
    function showAllLayers() {
        removeAll();//移除所有layer
        //标记组
        markerGroup();
        if (!latlngs) {
            return;
        }
        for (let i = 0; i < latlngs.length; i++) {
            let item = latlngs[i];
            if (item.hasOwnProperty("Marker")) {
                let marker = L.marker([item.Marker.lat, item.Marker.lng]).addTo(map);
                markerInit(marker);
            }
            if (item.hasOwnProperty("Rectangle")) {
                let rectangle = L.rectangle([item.Rectangle.map(x => ([x.lat, x.lng]))]).addTo(map);
                polygonInit(rectangle);
            }
            if (item.hasOwnProperty("Polygon")) {
                let polygon = L.polygon([item.Polygon.map(x => ([x.lat, x.lng]))]).addTo(map);
                polygonInit(polygon);
            }
        }
    }

    //获取经纬度数组和点所属多边形数组
    function getAllLayers() {
        latlngs = [];
        pointBelongs = [];
        let layers = map.pm.getGeomanLayers();
        if (layers) {
            for (let i = 0; i < layers.length; i++) {
                //标记
                if (layers[i].pm._shape === 'Marker') {
                    latlngs.push({'Marker': layers[i]._latlng});
                    let parent = getPolygonIncludePoint(layers[i]);
                    if (parent) {
                        pointBelongs.push([layers[i], parent]);
                    }
                }
                //矩形
                if (layers[i].pm._shape === 'Rectangle') {
                    latlngs.push({'Rectangle': layers[i]._latlngs[0]});
                }
                //多边形
                if (layers[i].pm._shape === 'Polygon') {
                    latlngs.push({'Polygon': layers[i]._latlngs[0]});
                }
            }
        }
    }

    //获取后台数据
    function getData() {
        //模拟后台传递过来的数据
        latlngs.push({'Marker': {lat: 36.70820977, lng: 119.10748243}});
        latlngs.push({
            'Rectangle': [
                {lat: 56.559482483762245, lng: 48.16406250000001},
                {lat: 63.31268278043484, lng: 48.16406250000001},
                {lat: 63.31268278043484, lng: 74.35546875000001},
                {lat: 56.559482483762245, lng: 74.35546875000001}
            ]
        });
        latlngs.push({
            'Polygon': [
                {lat: 60.413852350464936, lng: 97.03125000000001},
                {lat: 49.61070993807422, lng: 105.29296875},
                {lat: 55.178867663282006, lng: 128.84765625000003},
                {lat: 64.24459476798195, lng: 148.00781250000003},
                {lat: 68.9110048456202, lng: 134.47265625000003},
                {lat: 71.69129271863999, lng: 118.47656250000001},
                {lat: 68.9110048456202, lng: 112.14843750000001},
                {lat: 66.72254132270653, lng: 93.69140625}
            ]
        });
        //展示图层
        showAllLayers();
    }

    //模拟后台获取数据
    getData();

    //保存后台 todo
    function save() {

    }

    //生成geojson数据
    function toGeoJson(layer) {
        var layerArray = [];
        if (layer.pm && layer.pm._enabled === false && layer.pm.options.draggable === true) {
            layerArray.push(layer);
        }
        let geojson = L.layerGroup(layerArray).toGeoJSON();
        for (var n = 0; n < geojson.features.length; n++) {
            var nowJson = JSON.stringify(geojson.features[n]);
            for (var m = n + 1; m < geojson.features.length; m++) {
                var nextJson = JSON.stringify(geojson.features[m]);
                if (nowJson === nextJson) {
                    geojson.features.splice(n, 1);
                }
            }
        }
        return geojson;
    }

    //找出包含此点的多边形
    function getPolygonIncludePoint(pointLayer) {
        let polygonGeoJsonArray = [];
        let layers = map.pm.getGeomanLayers();
        if (layers) {
            for (let i = 0; i < layers.length; i++) {
                //矩形
                if (layers[i].pm._shape === 'Rectangle') {
                    polygonGeoJsonArray.push(toGeoJson(layers[i]));
                }
                //多边形
                if (layers[i].pm._shape === 'Polygon') {
                    polygonGeoJsonArray.push(toGeoJson(layers[i]));
                }
            }
        }
        var polygons = L.geoJson(polygonGeoJsonArray);
        return leafletPip.pointInLayer(pointLayer._latlng, polygons, true);
    }

    //移除全部layer
    function removeAll() {
        //移除所有layer
        map.pm.getGeomanLayers().map(x => {
            map.removeLayer(x)
        });
        if (heatLayer) {
            map.removeLayer(heatLayer);
        }
        if (markers) {
            map.removeLayer(markers);
        }
    }
</script>
</html>
